<!doctype html>

<html>

<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8" />

  <title>Basis Demos: Entity basic</title>

  <link rel="stylesheet" type="text/css" title="Default Style" href="../../style/tree/compat/style.css" media="screen" />
  <link rel="stylesheet" type="text/css" title="Default Style" href="../../style/form/default/style.css" media="screen" />
  <link rel="stylesheet" type="text/css" title="Default Style" href="../../style/button/new/style.css" media="screen" />

  <style type="text/css" id="demo-css">
    .Basis-Tree
    {
      border: 1px solid #AAA;
      width: 240px;
      height: 300px;
      overflow: auto;
      overflow-y: scroll;
      overflow-x: hidden;
      float: left;
      margin-right: 10px;
    }

    .form-content
    {
      overflow: hidden;
    }
  </style>
  <!--[if lt IE 7]>
  <style type="text/css">
    BODY
    {
      font-size: x-small;
    }
  </style>
  <![endif]-->

  <!--[if IE 7]>
  <![endif]-->


  <script type="text/javascript" src="../../basis-all.js"></script>

  <script type="text/javascript" src="../demo.js"></script>
</head>

<body>
  <h1>Basis Demos: Entity basic</h1>

  <p id="demo-summary">
    В данной демонстации показана реализация простого интерфейса редактирования данных в связке список-форма с использованием basis.entity.
  </p>
  <div id="demo-description">
    <p>В дереве (basis.ui.tree.Tree) представлен список статей. При выборе одного из пунктов его данные (данные статьи) загружаются в форму (basis.ui.form.FormContent), при это не происходит никакого копирования или присвоения данных. Загрузка данных осуществляется через связывание листа дерева (basis.ui.tree.TreeNode) с формой, путем назначения посленей делегатом (form.setDelegate) выбранного листа. Это...</p>
  </div>

  <div id="demo-container"></div>

  <script id="demo-javascript" type="text/javascript">
    
    // Определяем новый тип данных.
    var Article = new basis.entity.EntityType({
      // Необязательное поле, используется в основном для отладки.
      name: 'Article',
      
      // Опеределяем какое поле является ключом. Это так же необязательное поле и в данной
      // демонстрации не используется, однако лучше определять ключевое поле, чтобы придать
      // уникальность и дать возможность адресовать к нужным данным.
      id: 'id',

      // Определяем набор полей
      fields: {
        id: Number,
        title: String,
        content: String
      }
    });

    // Генерируем тестовый набор данных.
    for (var i = 0; i < 10; i++)
      Article({
        id: i,
        title: 'title #' + i,
        content: 'content #' + i
      });

    // Создаем новый класс для листьев дерева с переопределеной функцией формирования заголовка.
    // Данный код вынесен отдельно для наглядности и мог бы быть вставлен непосрественно в
    // конструкторе дерева, без заведения переменной для нового класса.
    var MyTreeNode = basis.Class.create(basis.ui.tree.Node, {
      binding: {
        events: 'update',
        getter: Function.getter('data', '[{id}] {title}')
      }
    });

    // Создаем дерево
    var myTree = new basis.ui.tree.Tree({
      // Определяем класс для дочерних узлов (описан выше)
      childClass: MyTreeNode,

      // Задаем управляющую коллекцию. Так как мы используем Entity, то нет необходимости в
      // создании массива для хранения списка всех экземпляров данных, а так же нет необходимости
      // отслеживать изменения в данном наборе: новые элементы будут добавляться, удаляться и
      // изменяться по мере работы непосредственно с самими данными.
      dataSource: Article.all,

      // Определяем сортировку для дочерних узлов: сортируем по node.data.title.
      sorting: Function.getter('data.title'),

      // Задаем обработчик на событие изменения выборки (Selection).
      selection: {}
    });

    myTree.selection.addHandler({
      datasetChanged: function(){
        // В данном контесте this указывает на выборку (myTree.selection).

        // Назначаем делегатом формы первый выбранный элемент. Если не выбрано ни одного узла
        // (this.pick() равно undefined), то форма останется без делегата (по сути не будет
        // привязана к каким либо данным).
        myForm.setDelegate(this.pick());
      }
    });

    // Создаем форму
    var myForm = new basis.ui.form.FormContent({
      // Делаем форму недоступной для редактирования на первоначальном этапе, так как к ней еще
      // не привязаны данные и соответственно нечего редактировать.
      disabled: true,

      // Создаем поля формы.
      // Важно, чтобы имена полей (свойство name) соотвествовали полям редактируемых данных. Только
      // в этом случае будет обеспечена правильная работа метода myForm.loadData, а так же данные
      // полученные путем сериализации формы (myForm.serialize()) будут "совместимы" с редактируемым
      // типом данных и смогут быть использованы для обновления целевого (редактируемого) объекта.
      childNodes: [
        {
          type: 'text',
          name: 'title',
          title: 'Title'
        },
        {
          type: 'textarea',
          name: 'content',
          title: 'Content'
        }
      ]
    });

    // Добавляем собственные обработчики событий.
    // Событие смены делегата
    myForm.addHandler({
      delegateChanged: function(object, oldDelegate){
        // В данном контесте this указывает на форму (myForm).

        if (this.delegate)
        {
          // Если делегат назначен - загружаем данные в поля формы. Так как при назначении
          // делегата объект начинает указывать на те же данные что и делегат (свойство data), мы
          // можем оперировать с ними как будто они собственные (принадлежат форме), без обращения
          // непосрественно к делегату. В данном случае this.data === this.delegate.data.
          this.loadData(this.data);

          // Делаем форму активной.
          this.enable();
        }
        else
        {
          // Так как форма больше не привязана к данным - очищаем поля.
          this.reset();

          // Делаем форму НЕактивной.
          this.disable();
        }
      }
    });

    // Создаем панель с кнопками
    var myButtonPanel = new basis.ui.button.ButtonPanel({
      childNodes: [
        {
          // Функция сохранения
          caption: 'Save',
          click: function(){
            // Так как форма указывает на те же данные, что и редактируемый объект мы можем вызывать
            // метод обновления самой формы (myForm.update). В случае если никакого объекта не привязано
            // то будут обновлен собственный контейнер данных (myForm.data), что не имеет никакого 
            // эффекта. Но так как в поведении формы мы ограничили ее доступность к редактированию, которое
            // доступно только когда форме задан делегат, то в таком случае возможно лишь "сохранение"
            // путого объекта
            myForm.update(myForm.serialize());
          }
        },
        {
          // Функция отмены (сброс в начальное состояние).
          caption: 'Cancel',
          click: function(){
            // Если к форме привязаны данные (задан делегат) загружаем данные из объекта какими они были
            // до сохранения. Опять же, так как к форме привязан делегат, то ее контейнер данных содержит
            // данные редактируемого объекта. Если делегат не назначен (форме) то форма будет содержать
            // пустой контейнер данных и данный метод не будет иметь эффекта.
            myForm.loadData(myForm.data);
          }
        }
      ]
    });

    // Вставляем компоненты в документ
    basis.dom.insert('demo-container', [
      myTree.element,
      myForm.element,
      myButtonPanel.element
    ]);

  </script>  
</body>

</html>
